package org.kabeja.dxf.entity;

import org.kabeja.dxf.DXFConstants;
import org.kabeja.dxf.helpers.Point;
import org.kabeja.dxf.helpers.Vector;
import org.kabeja.math.MathUtils;
import org.kabeja.math.ParametricPlane;

/**
 * @author shutao
 * @since 2022/4/24 17:41
 */
public class DXFEllipse extends DXFEntity {
    public static final double DEFAULT_END_PARAMETER = 6.283185307179586D;
    public static final double DEFAULT_START_PARAMETER = 0.0D;
    public static final int INTEGRATION_STEPS = 15;
    private double ratio = 1.0D;
    private double startParameter = 0.0D;
    private double endParameter = 6.283185307179586D;
    private Point center = new Point();
    private Vector majorAxisDirection = new Vector();
    private boolean counterclockwise;

    public DXFEllipse() {
        this.setLineType(this.getType());
        this.center = new Point();
    }

    @Override
    public Bounds getBounds() {
        double var1 = this.getRotationAngle();
        Bounds var3 = new Bounds();
        ParametricPlane var4 = new ParametricPlane(this.center, this.getExtrusion().getDirectionX(), this.getExtrusion().getDirectionY(), this.getExtrusion().getNormal());
        if (this.startParameter == 0.0D && this.endParameter == 6.283185307179586D && var1 == 0.0D) {
            double var23 = this.getHalfMajorAxisLength();
            var3.addToBounds(var4.getPoint(var23, var23));
            var3.addToBounds(var4.getPoint(-var23, -var23));
        } else {
            byte var5 = 40;
            double var6 = (this.endParameter - this.startParameter) / (double)var5;
            double var8 = this.startParameter;
            double var10 = this.getHalfMajorAxisLength();
            double var10000 = var10 * this.ratio;
            Vector var14 = MathUtils.crossProduct(this.getExtrusion().getNormal(), this.getMajorAxisDirection());
            var14 = MathUtils.scaleVector(var14, this.ratio);

            for(int var15 = 0; var15 <= var5; ++var15) {
                Vector var16 = MathUtils.scaleVector(this.getMajorAxisDirection(), Math.cos(var8));
                Vector var17 = MathUtils.scaleVector(var14, Math.sin(var8));
                double var18 = var16.getX() + var17.getX();
                double var20 = var16.getY() + var17.getY();
                Point var22 = var4.getPoint(var18, var20);
                var3.addToBounds(var22);
                var8 += var6;
            }
        }

        return var3;
    }

    public Point getCenterPoint() {
        return this.center;
    }

    public void setCenterPoint(Point var1) {
        this.center = var1;
    }

    public Vector getMajorAxisDirection() {
        return this.majorAxisDirection;
    }

    public void setMajorAxisDirection(Vector var1) {
        this.majorAxisDirection = var1;
    }

    public double getEndParameter() {
        return this.endParameter;
    }

    public void setEndParameter(double var1) {
        if (var1 < 0.0D) {
            this.endParameter = 6.283185307179586D + var1;
        } else {
            this.endParameter = var1;
        }

    }

    public double getRatio() {
        return this.ratio;
    }

    public void setRatio(double var1) {
        this.ratio = var1;
    }

    public double getStartParameter() {
        return this.startParameter;
    }

    public void setStartParameter(double var1) {
        if (var1 < 0.0D) {
            this.startParameter = 6.283185307179586D + var1;
        } else {
            this.startParameter = var1;
        }

    }

    @Override
    public String getType() {
        return DXFConstants.ENTITY_TYPE_ELLIPSE;
    }

    public double getHalfMajorAxisLength() {
        return this.majorAxisDirection.getLength();
    }

    public Point getLocalPointAt(double var1) {
        Point var3 = new Point();
        double var4 = this.getHalfMajorAxisLength();
        double var6 = var4 * this.ratio;
        double var8 = var4 * Math.cos(var1);
        double var10 = var6 * Math.sin(var1);
        double var12 = this.getRotationAngle();
        if (var12 != 0.0D) {
            double var14 = var8;
            var8 = var8 * Math.cos(var12) - var10 * Math.sin(var12);
            var10 = var14 * Math.sin(var12) + var10 * Math.cos(var12);
        }

        var3.setX(var8);
        var3.setY(var10);
        var3.setZ(0.0D);
        return var3;
    }

    public Point getPointAt(double var1) {
        ParametricPlane var3 = new ParametricPlane(this.center, this.getExtrusion().getDirectionX(), this.getExtrusion().getDirectionY(), this.getExtrusion().getNormal());
        Vector var4 = MathUtils.crossProduct(this.getExtrusion().getNormal(), this.getMajorAxisDirection());
        var4 = MathUtils.scaleVector(var4, this.ratio);
        Vector var5 = MathUtils.scaleVector(this.getMajorAxisDirection(), Math.cos(var1));
        Vector var6 = MathUtils.scaleVector(var4, Math.sin(var1));
        double var7 = var5.getX() + var6.getX();
        double var9 = var5.getY() + var6.getY();
        return var3.getPoint(var7, var9);
    }

    public Point getLocalStartPoint() {
        return this.getLocalPointAt(this.startParameter);
    }

    public Point getLocalEndPoint() {
        return this.getLocalPointAt(this.endParameter);
    }

    public double getRotationAngle() {
        return MathUtils.getAngle(DXFConstants.DEFAULT_X_AXIS_VECTOR, this.majorAxisDirection);
    }

    @Override
    public double getLength() {
        byte var1 = 15;
        double var2 = (this.endParameter - this.startParameter) / (double)var1;
        double var4 = this.getHalfMajorAxisLength();
        double var6 = var4 * this.ratio;
        double var8 = this.startParameter;
        double var10 = 0.0D;
        double var12 = 0.0D;

        for(int var14 = 0; var14 < var1; ++var14) {
            double var15 = var2 / 2.0D + var8;
            var10 = var8 + var2;
            double var17 = Math.sqrt(Math.pow(var4 * Math.sin(var8), 2.0D) + Math.pow(var6 * Math.cos(var8), 2.0D));
            double var19 = Math.sqrt(Math.pow(var4 * Math.sin(var15), 2.0D) + Math.pow(var6 * Math.cos(var15), 2.0D));
            double var21 = Math.sqrt(Math.pow(var4 * Math.sin(var10), 2.0D) + Math.pow(var6 * Math.cos(var10), 2.0D));
            var12 += (var17 + 4.0D * var19 + var21) * (var2 / 6.0D);
            var8 = var10;
        }

        return var12;
    }

    public boolean isCounterClockwise() {
        return this.counterclockwise;
    }

    public void setCounterClockwise(boolean var1) {
        this.counterclockwise = var1;
    }
}
